﻿using com.yoozoo.gta.Extension;
using System;
using System.Collections.Generic;
using com.yoozoo.gta.Extension.UGUI.ScreenOrientationEx;
using Gameplay.PVE.Survivor;
using UnityEngine;
using WorldMap;
using Yoozoo.Framework.Core;
using Yoozoo.Gameplay.RTS;
using Yoozoo.Gameplay.RTS.Proto;
using Yoozoo.Managers.ResourceManagerV2.Framework.Resource;
using Yoozoo.Managers.ResourceManagerV2.Runtime;
using Random = UnityEngine.Random;
public enum LineType
{
    arrow,
    line,
    assembly,
    wonderNpc,
    warning,
}
public class MarchLinePoint
{
    public int lineId;
    public GameObject pathStartObj;
    public GameObject pathEndObj;
    public List<SpriteRenderer> imageStart = new List<SpriteRenderer>(4);
    public List<SpriteRenderer> imageEnd = new List<SpriteRenderer>(4);
    internal void OnReset()
    {
        imageStart.Clear();
        imageEnd.Clear();
    }
}
public class LineInfo
{
    public uint id;
    public Vector2 startPos;
    public Vector2 endPos;
    public Color color;
    public LineType lineType;
    public float speed;
    public bool isPart;
    public bool isHeadPart;
    public int team;
    public bool isAssembly;
    public float length
    {
        get
        {
            return Vector2.Distance(startPos, endPos);
        }
    }

    //public LineInfo(ref LineInfo model)
    //{
    //    id = model.id;
    //    startPos = model.startPos;
    //    endPos = model.endPos;
    //    color = model.color;
    //    speed = model.speed;
    //    isPart = model.isPart;
    //    isHeadPart = model.isHeadPart;
    //    lineType = model.lineType;
    //    team = model.team;
    //}
    public void Copy(LineInfo from)
    {
        id = from.id;
        startPos = from.startPos;
        endPos = from.endPos;
        color = from.color;
        speed = from.speed;
        isPart = from.isPart;
        isHeadPart = from.isHeadPart;
        lineType = from.lineType;
        team = from.team;
    }

    internal void OnReset()
    {
        id = default;
        startPos = Vector2.zero;
        endPos = Vector2.zero;
        color = default;
        speed = default;
        isPart = default;
        isHeadPart = default;
        lineType = default;
        team = default;
    }
}

public class DrawLineTool : SingletonMono<DrawLineTool>
{
    private uint m_lineIdSeed;
    private uint lineID
    {
        get
        {
            if (m_lineIdSeed == uint.MaxValue)
            {
                m_lineIdSeed = 0;
            }
            return ++m_lineIdSeed;
        }
    }

    private const int LINE_MAX_COUNT = 720;
    private const int Pre_LINE_MAX_COUNT = 20;
    //private const float LINE_WIDTH = 0.1f;
    private const float LINE_SEGMENT_MAX = 100000;

    private Transform selfTrans;
    public Transform followTrans;
    public static float pointScale = 0.005f;
    private bool meshIsDirty;
    private Vector2[] uvs;
    private Vector3[] vertices;
    private Vector4[] tangents;
    private Color[] colors;
    private int[] triangles;

    private Vector2[] uvs2;
    private Vector3[] vertices2;
    private Vector4[] tangents2;
    private Color[] colors2;
    private int[] triangles2;

    
    private Vector2[] uvs3;
    private Vector3[] vertices3;
    private Vector4[] tangents3;
    private Color[] colors3;
    private int[] triangles3;
    
    private Vector2[] uvs4;
    private Vector3[] vertices4;
    private Vector4[] tangents4;
    private Color[] colors4;
    private int[] triangles4;
    
    private Vector2 viewLeftDown;
    public Vector2 ViewLeftDown
    {
        get
        {
            return viewLeftDown;
        }
    }

    private Vector2 viewRightTop;
    public Vector2 ViewRightTop
    {
        get
        {
            return viewRightTop;
        }
    }

    public Vector2 viewRect;
    public Mesh arrowMesh;
    public Mesh lineMesh;
    public Mesh assembleMesh;
    public Mesh warningMesh;
    public Material arrowMat;
    public Material lineMat;
    public Material assemblyLineMat;
    public Material warningMat;
    private string lineMatPath;
    private string lineMathDotPath;
    private string assemblyLineMatPath;
    private string warningMatPath;
    public int lastVisiableLineCount;
    public int materialType = 0;//0箭头  1圆点
    public float LINE_WIDTH = 0.2f;
    public float selfScale = 1.5f;
    public float gatherScale = 2.5f;
    public float warningScale = 1.5f;
    public float allScale = 1.0f;
    private Vector3 ViewCenterPos;
    public Vector2 OffsetFactor = new Vector2(1f,1f);
    public float lineSpeed = 1;
    private List<LineInfo> arrows = new List<LineInfo>(MarchManager.MarchEntityPoolNum);
    private List<LineInfo> lines = new List<LineInfo>(MarchManager.MarchEntityPoolNum);
    private List<LineInfo> assemblelines = new List<LineInfo>(MarchManager.MarchEntityPoolNum);
    private List<LineInfo> warningLines = new List<LineInfo>(20);
    private bool inited;

    //private List<List<Vector2>> pointsPool;
    private List<List<uint>> lineIdPool = new List<List<uint>>(MarchManager.MarchEntityPoolNum);
    private const int lineLength = 5;

    private void InitPool()
    {
        /*pointsPool = new List<List<Vector2>>(MarchManager.MarchEntityPoolNum);
        for (int i = 0; i < MarchManager.MarchEntityPoolNum; i++)
        {
            pointsPool.Add(new List<Vector2>(lineLength));
        }*/

        lineIdPool = new List<List<uint>>(MarchManager.MarchEntityPoolNum);
        for (int i = 0; i < MarchManager.MarchEntityPoolNum; i++)
        {
            lineIdPool.Add(new List<uint>(lineLength - 1));
        }
    }

    public void SetLayer(int layer)
    {
        this.layer = layer;
    }

    private void InitSurvivalMaterial(Material mat)
    {
        mat.SetFloat("_DepthOffset",-0.05f);
    }

    public bool isSurvivor = false;
    
    public override void Initialize(Options options = null)
    {
        base.Initialize();
        isSurvivor = SurvivorManager.IsInGame;
        m_lineIdSeed = 0;
        selfTrans = transform;
        int defaultLayer = LayerMask.NameToLayer("MarchHud");
        layer = defaultLayer;
        uvs = new Vector2[LINE_MAX_COUNT * 4];
        vertices = new Vector3[LINE_MAX_COUNT * 4];
        tangents = new Vector4[LINE_MAX_COUNT * 4];
        colors = new Color[LINE_MAX_COUNT * 4];
        triangles = new int[LINE_MAX_COUNT * 6];

        uvs2 = new Vector2[Pre_LINE_MAX_COUNT * 4];
        vertices2 = new Vector3[Pre_LINE_MAX_COUNT * 4];
        tangents2 = new Vector4[Pre_LINE_MAX_COUNT * 4];
        colors2 = new Color[Pre_LINE_MAX_COUNT * 4];
        triangles2 = new int[Pre_LINE_MAX_COUNT * 6];

        uvs3 = new Vector2[Pre_LINE_MAX_COUNT * 4];
        vertices3 = new Vector3[Pre_LINE_MAX_COUNT * 4];
        tangents3 = new Vector4[Pre_LINE_MAX_COUNT * 4];
        colors3 = new Color[Pre_LINE_MAX_COUNT * 4];
        triangles3 = new int[Pre_LINE_MAX_COUNT * 6];
        
        uvs4 = new Vector2[Pre_LINE_MAX_COUNT * 4];
        vertices4 = new Vector3[Pre_LINE_MAX_COUNT * 4];
        tangents4 = new Vector4[Pre_LINE_MAX_COUNT * 4];
        colors4 = new Color[Pre_LINE_MAX_COUNT * 4];
        triangles4 = new int[Pre_LINE_MAX_COUNT * 6];
        
        arrowMesh = new Mesh();
        lineMesh = new Mesh();
        assembleMesh = new Mesh();
        warningMesh = new Mesh();
        lineMatPath = "Materials/DrawLine/mat_Line_aixin";
        lineMathDotPath = "Materials/DrawLine/mat_Line_arrow_gradient";
        assemblyLineMatPath = "Materials/DrawLine/mat_Line_assemblyArrow";
        warningMatPath = "Materials/DrawLine/mat_Line_warning";
        UMTResource.LoadAsset("Assets/ResourcesAssets/"+ lineMatPath + ".mat", (string assetName, object asset, float duration, object userData) =>
        {
            arrowMat = (Material)asset;
            if (isSurvivor)
            {
                InitSurvivalMaterial(arrowMat);
            }
        }, (string assetName, LoadResourceStatus status, string errorMessage, object userData) =>
        {
            Debug.LogErrorFormat("asset:{0} failed :{1}", assetName, errorMessage);
        });

        UMTResource.LoadAsset("Assets/ResourcesAssets/" + lineMathDotPath + ".mat", (string assetName, object asset, float duration, object userData) =>
        {
            lineMat = (Material)asset;
        }, (string assetName, LoadResourceStatus status, string errorMessage, object userData) =>
        {
            Debug.LogErrorFormat("asset:{0} failed :{1}", assetName, errorMessage);
        });
        
        UMTResource.LoadAsset("Assets/ResourcesAssets/" + assemblyLineMatPath + ".mat", (string assetName, object asset, float duration, object userData) =>
        {
            assemblyLineMat = (Material)asset;
        }, (string assetName, LoadResourceStatus status, string errorMessage, object userData) =>
        {
            Debug.LogErrorFormat("asset:{0} failed :{1}", assetName, errorMessage);
        });
        UMTResource.LoadAsset("Assets/ResourcesAssets/" + warningMatPath + ".mat", (string assetName, object asset, float duration, object userData) =>
        {
            warningMat = (Material)asset;
        }, (string assetName, LoadResourceStatus status, string errorMessage, object userData) =>
        {
            Debug.LogErrorFormat("asset:{0} failed :{1}", assetName, errorMessage);
        });


        InitPool();
        // 添加横竖版监听
        ScreenOrientManager.GetInstance().AddOrientationChangeCallBack("RTSDrawLine",OnOrientationChange);
        inited = true;
    }
    private int _lodLevel;
    private int _ZTestLevel = 4;
    public void OnLodChanged(int lodLevel)
    {
        if (_lodLevel != lodLevel)
        {
            int ZTest;
            if (lodLevel >= 4)
            {
                ZTest = 8;
            }
            else
            {
                ZTest = 4;
            }
            if (ZTest!=_ZTestLevel)
            {
                _ZTestLevel = ZTest;
                arrowMat.SetInt("_ZTest", ZTest);
            }
            _lodLevel = lodLevel;
        }
    }

    public void OnOrientationChange(ScreenOrientation orientation)
    {
        float scale = allScale;
        bool isPort = ScreenOrientManager.GetInstance().GetScreenOrientationIsPortrait();
        if (isPort)
        {
            scale = 0.5f;
        }
        else
        {
            scale = 1.0f;
        }

        if (scale != allScale)
        {
            meshIsDirty = true;
            allScale = scale;
        }
    }

    private void OnDestroy()
    {
        foreach (var arrow in arrows)
        {
            RTSClassPoolManager.RecoverLineInfo(arrow);
        }
        arrows.Clear();
        arrows = null;
        uvs = null;
        vertices = null;
        tangents = null;
        colors = null;
        triangles = null;

        foreach (var line in lines)
        {
            RTSClassPoolManager.RecoverLineInfo(line);
        }
        lines.Clear();
        lines = null;
        uvs2 = null;
        vertices2 = null;
        tangents2 = null;
        colors2 = null;
        triangles2 = null;

        foreach (var line in assemblelines)
        {
            RTSClassPoolManager.RecoverLineInfo(line);
        }
        assemblelines.Clear();
        assemblelines = null;
        uvs3 = null;
        vertices3 = null;
        tangents3 = null;
        colors3 = null;
        triangles3 = null;
        
        foreach (var line in warningLines)
        {
            RTSClassPoolManager.RecoverLineInfo(line);
        }
        warningLines.Clear();
        warningLines = null;
        uvs4 = null;
        vertices4 = null;
        tangents4 = null;
        colors4 = null;
        triangles4 = null;
        
        if (arrowMesh != null)
        {
            Destroy(arrowMesh);
        }
        arrowMesh = null;

        if (lineMesh != null)
        {
            Destroy(lineMesh);
        }
        lineMesh = null;

        if (assembleMesh!=null)
        {
            Destroy(assembleMesh);
        }

        assembleMesh = null;

        if (warningMesh != null)
        {
            Destroy(warningMesh);
        }
        
        lineMatPath = null;
        if (arrowMat)
        {
            UMTResource.UnloadAsset(arrowMat);
            arrowMat = null;
        }

        if (lineMat)
        {
            UMTResource.UnloadAsset(lineMat);
            lineMat = null;
        }

        if (assemblyLineMat)
        {
            UMTResource.UnloadAsset(assemblyLineMat);
            assemblyLineMat = null;
        }

        if (warningMat)
        {
            UMTResource.UnloadAsset(warningMat);
            warningMat = null;
        }
        ScreenOrientManager.GetInstance().RemoveOrientationChangeCallBack("RTSDrawLine");
    }

    private void SetClipRect(int width, int height)
    {
        viewRect.x = (1 + OffsetFactor.x) * width;
        viewRect.y = (1 + OffsetFactor.y) * height;
    }

    private WorldCameraManager worldCameraManager;
    private int _width, _height;
    private float minHeight;
    public void SetWHRect(float width, float height,float minHeight)
    {
        this._width = Mathf.CeilToInt(width);
        this._height = Mathf.CeilToInt(height);
        this.minHeight = minHeight;
    }

    private int layer;
    private void Update()
    {
        if (!inited || followTrans==null || followTrans.Invalid())
        {
            return;
        }
        SetClipRect(_width,_height);

        // 射线与平面求交点，得到当前视线中心点
        ViewCenterPos = WorldMapUtility.GetIntersectionWithLineAndPlane(followTrans.position, followTrans.forward,
            Vector3.up, Vector3.zero);

        var lastViewLeftDown = new Vector2(ViewCenterPos.x - viewRect.x / 2, ViewCenterPos.z - viewRect.y / 2 );
        if (viewLeftDown != lastViewLeftDown)
        {
            viewLeftDown = lastViewLeftDown;
            meshIsDirty = true;
        }
        var lastViewRightTop = new Vector2(ViewCenterPos.x + viewRect.x / 2, ViewCenterPos.z + viewRect.y / 2 );
        if (viewRightTop != lastViewRightTop)
        {
            viewRightTop = lastViewRightTop;
            meshIsDirty = true;
        }

        if (meshIsDirty)
        {
            ReBuildMesh();
        }

        if (arrowMat != null)
        {
            Graphics.DrawMesh(arrowMesh, selfTrans.position, Quaternion.Euler(Vector3.zero), arrowMat, layer);
        }

        if (lineMat != null)
        {
            Graphics.DrawMesh(lineMesh, selfTrans.position, Quaternion.Euler(Vector3.zero), lineMat, layer);
        }

        if (assemblyLineMat)
        {
            Graphics.DrawMesh(assembleMesh, selfTrans.position, Quaternion.Euler(Vector3.zero), assemblyLineMat, layer);
        }
        
        if (warningMat)
        {
            Graphics.DrawMesh(warningMesh, selfTrans.position, Quaternion.Euler(Vector3.zero), warningMat, layer);
        }
        ChangeLinesColor();
    }


    //private void StressTest()
    //{
    //    viewRect = new Vector2(1, 1);

    //    for (int i = 0; i < 100; i++)
    //    {
    //        LineInfo test = new LineInfo();
    //        test.startPos = new Vector2(i * 2, 0);
    //        test.endPos = new Vector2(298, -74*2);
    //        test.color = new Color(Random.Range(0,1f), Random.Range(0, 1f), Random.Range(0, 1f));
    //        test.speed = Random.Range(1, 4);
    //        AddLine(ref test);
    //    }

    //    for (int i = 0; i < 100; i++)
    //    {
    //        LineInfo test = new LineInfo();
    //        test.startPos = new Vector2(0, -i * 2);
    //        test.endPos = new Vector2(298, -74*2);
    //        test.color = new Color(Random.Range(0, 1f), Random.Range(0, 1f), Random.Range(0, 1f));
    //        test.speed = Random.Range(1, 4);
    //        AddLine(ref test);
    //    }
    //}

    #region CHUNK裁剪
    /// <summary>
    /// Liany-Barsky算法
    /// </summary>
    /// <param name="p"></param>
    /// <param name="q"></param>
    /// <param name="u1"></param>
    /// <param name="u2"></param>
    private bool ViewClipCore(float p, float q, ref float u1, ref float u2)
    {
        var isVisiable = true;
        float r;
        if (p < 0)
        {
            r = q / p;
            if (r > u2)
            {
                isVisiable = false;
            }
            else if (r > u1)
            {
                u1 = r;
            }
        }
        else if (p > 0)
        {
            r = q / p;
            if (r < u1)
            {
                isVisiable = false;
            }
            else if (r < u2)
            {
                u2 = r;
            }
        }
        else if (q < 0)
        {
            isVisiable = false;
        }

        return isVisiable;
    }

    private bool ViewClip(LineInfo line, LineInfo clipLine)
    {

        clipLine.Copy(line);

        float u1 = 0, u2 = 1, dx = line.endPos.x - line.startPos.x, dy = 0;
        if (ViewClipCore(-dx, line.startPos.x - viewLeftDown.x, ref u1, ref u2))
        {
            if (ViewClipCore(dx, viewRightTop.x - line.startPos.x, ref u1, ref u2))
            {
                dy = line.endPos.y - line.startPos.y;
                if (ViewClipCore(-dy, line.startPos.y - viewLeftDown.y, ref u1, ref u2))
                {
                    if (ViewClipCore(dy, viewRightTop.y - line.startPos.y, ref u1, ref u2))
                    {
                        if (u2 < 1)
                        {
                            clipLine.endPos.x = line.startPos.x + u2 * dx;
                            clipLine.endPos.y = line.startPos.y + u2 * dy;
                        }
                        if (u1 > 0)
                        {
                            clipLine.startPos.x = line.startPos.x + u1 * dx;
                            clipLine.startPos.y = line.startPos.y + u1 * dy;
                        }
                        return true;
                    }
                }
            }
        }

        return false;
    }
    #endregion

    private void CalculateLineRect(LineInfo line, out Vector2 p1, out Vector2 p2, out Vector2 p3, out Vector2 p4)
    {
        float width = LINE_WIDTH / 2f;
        if (line.lineType == LineType.assembly)
        {
            width = LINE_WIDTH / 2f * gatherScale;
        }
        else if (line.lineType == LineType.wonderNpc)
        {
            width = LINE_WIDTH / 2f * selfScale;
        }
        else if (line.lineType == LineType.warning)
        {
            width = LINE_WIDTH / 2f * warningScale;
        }
        else
        {
            if (line.team == 0)
            {
                width = LINE_WIDTH / 2f * selfScale;
            }
        }
        width = width * (this._height / this.minHeight) * allScale;


        var verticalDir = line.endPos - line.startPos;
        var verticalOffset = new Vector2(-verticalDir.y, verticalDir.x).normalized * width;

        p1 = line.startPos - verticalOffset;
        p2 = line.startPos + verticalOffset;
        p3 = line.endPos + verticalOffset;
        p4 = line.endPos - verticalOffset;
    }

    private float height;

    public void SetHeight(float height)
    {
        this.height = height;
    }

    private void CalculateMesh(Vector3[] vertices, Vector2[] uvs, Vector4[] tangents,Color[] colors,int[] triangles,List<LineInfo> lines,int maxNum)
    {
        var lineIdx = 0;

        System.Array.Clear(vertices, 0, vertices.Length);
        System.Array.Clear(uvs, 0, uvs.Length);
        System.Array.Clear(tangents, 0, tangents.Length);
        System.Array.Clear(colors, 0, colors.Length);
        System.Array.Clear(triangles, 0, triangles.Length);

        foreach (var curOriginLine in lines)
        {
            if (lineIdx >= maxNum)
            {
                continue;
            }
            LineInfo curLine = RTSClassPoolManager.GetLineInfo();
            if (!ViewClip(curOriginLine, curLine))
            {
                RTSClassPoolManager.RecoverLineInfo(curLine);
                continue;
            }
            var verIdxBase = lineIdx * 4;
            Vector2 p1, p2, p3, p4;
            CalculateLineRect(curLine, out p1, out p2, out p3, out p4);
            vertices[verIdxBase + 0] = new Vector3(p1.x, height, p1.y);
            vertices[verIdxBase + 1] = new Vector3(p2.x, height, p2.y);
            vertices[verIdxBase + 2] = new Vector3(p3.x, height, p3.y);
            vertices[verIdxBase + 3] = new Vector3(p4.x, height, p4.y);

            tangents[verIdxBase + 0] = new Vector4(lineSpeed, 0, 0, 0);
            tangents[verIdxBase + 1] = new Vector4(lineSpeed, 0, 0, 0);
            tangents[verIdxBase + 2] = new Vector4(lineSpeed, 0, 0, 0);
            tangents[verIdxBase + 3] = new Vector4(lineSpeed, 0, 0, 0);

            colors[verIdxBase + 0] = curLine.color;
            colors[verIdxBase + 1] = curLine.color;
            colors[verIdxBase + 2] = curLine.color;
            colors[verIdxBase + 3] = curLine.color;
            if (curLine.isPart)
            {
                if (curLine.isHeadPart)
                {
                    colors[verIdxBase + 2].a = 0;
                    colors[verIdxBase + 3].a = 0;
                }
                else
                {
                    colors[verIdxBase + 0].a = 0;
                    colors[verIdxBase + 1].a = 0;
                }
            }

            var lineLength = curLine.length;
            //uvs[verIdxBase + 0] = new Vector2(1, 0);
            //uvs[verIdxBase + 1] = new Vector2(0, 0);
            //uvs[verIdxBase + 2] = new Vector2(0, lineLength / LINE_WIDTH);
            //uvs[verIdxBase + 3] = new Vector2(1, lineLength / LINE_WIDTH);
            float width;
            if (curLine.lineType == LineType.assembly)
            {
                width = LINE_WIDTH * gatherScale;
            }
            else if (curLine.lineType == LineType.wonderNpc)
            {
                width = LINE_WIDTH * selfScale;
            }
            else if (curLine.lineType == LineType.warning)
            {
                width = LINE_WIDTH * warningScale;
            }
            else
            {
                if (curLine.team == 0)
                {
                    width = LINE_WIDTH * selfScale;
                }
                else
                {
                    width = LINE_WIDTH;
                }
            }

            width *= allScale;
            var uvValue = curLine.lineType == LineType.line ?  0.5f :0f;
            uvs[verIdxBase + 0] = new Vector2(uvValue + 0.5f, 0);
            uvs[verIdxBase + 1] = new Vector2(uvValue,        0);
            uvs[verIdxBase + 2] = new Vector2(uvValue,        lineLength / width);
            uvs[verIdxBase + 3] = new Vector2(uvValue + 0.5f, lineLength / width);

            var triangleIdxBase = lineIdx * 6;
            triangles[triangleIdxBase + 0] = verIdxBase + 0;
            triangles[triangleIdxBase + 1] = verIdxBase + 1;
            triangles[triangleIdxBase + 2] = verIdxBase + 2;
            triangles[triangleIdxBase + 3] = verIdxBase + 0;
            triangles[triangleIdxBase + 4] = verIdxBase + 2;
            triangles[triangleIdxBase + 5] = verIdxBase + 3;

            lineIdx++;

            RTSClassPoolManager.RecoverLineInfo(curLine);
        }
    }


    private void CalculateMeshSpecial(Vector3[] vertices, Vector2[] uvs, Vector4[] tangents, Color[] colors, int[] triangles, List<LineInfo> lines, int maxNum)
    {
        var lineIdx = 0;

        System.Array.Clear(vertices, 0, vertices.Length);
        System.Array.Clear(uvs, 0, uvs.Length);
        System.Array.Clear(tangents, 0, tangents.Length);
        System.Array.Clear(colors, 0, colors.Length);
        System.Array.Clear(triangles, 0, triangles.Length);

        foreach (var curOriginLine in lines)
        {
            if (lineIdx >= maxNum)
            {
                continue;
            }
            LineInfo curLine = RTSClassPoolManager.GetLineInfo();
            if (!ViewClip(curOriginLine, curLine))
            {
                RTSClassPoolManager.RecoverLineInfo(curLine);
                continue;
            }
            var verIdxBase = lineIdx * 8; // 修改为只使用两个顶点和三个箭头顶点

            // 设置箭头顶点
            Vector2 p1, p2, p3, p4;
            Vector2 arrow5, arrow6, arrow7,arrow8;
            CalculateArrowVertices(curLine, out p1, out p2, out p3, out p4, out arrow5, out arrow6, out arrow7,out arrow8);

            vertices[verIdxBase + 0] = new Vector3(p1.x, height, p1.y);
            vertices[verIdxBase + 1] = new Vector3(p2.x, height, p2.y);
            vertices[verIdxBase + 2] = new Vector3(p3.x, height, p3.y);
            vertices[verIdxBase + 3] = new Vector3(p4.x, height, p4.y);
            vertices[verIdxBase + 4] = new Vector3(arrow5.x, height, arrow5.y);
            vertices[verIdxBase + 5] = new Vector3(arrow6.x, height, arrow6.y);
            vertices[verIdxBase + 6] = new Vector3(arrow7.x, height, arrow7.y);
            vertices[verIdxBase + 7] = new Vector3(arrow8.x, height, arrow8.y);

            // 其他信息保持不变
            tangents[verIdxBase + 0] = new Vector4(lineSpeed, 0, 0, 0);
            tangents[verIdxBase + 1] = new Vector4(lineSpeed, 0, 0, 0);
            tangents[verIdxBase + 2] = new Vector4(lineSpeed, 0, 0, 0);
            tangents[verIdxBase + 3] = new Vector4(lineSpeed, 0, 0, 0);
            tangents[verIdxBase + 4] = new Vector4(lineSpeed, 0, 0, 0);
            tangents[verIdxBase + 5] = new Vector4(lineSpeed, 0, 0, 0);
            tangents[verIdxBase + 6] = new Vector4(lineSpeed, 0, 0, 0);
            tangents[verIdxBase + 7] = new Vector4(lineSpeed, 0, 0, 0);

            colors[verIdxBase + 0] = curLine.color;
            colors[verIdxBase + 1] = curLine.color;
            colors[verIdxBase + 2] = curLine.color;
            colors[verIdxBase + 3] = curLine.color;
            colors[verIdxBase + 4] = curLine.color;
            colors[verIdxBase + 5] = curLine.color;
            colors[verIdxBase + 6] = curLine.color;
            colors[verIdxBase + 7] = curLine.color;
            if (curLine.isPart)
            {
                if (curLine.isHeadPart)
                {
                    colors[verIdxBase + 2].a = 0;
                    colors[verIdxBase + 3].a = 0;
                }
                else
                {
                    colors[verIdxBase + 0].a = 0;
                    colors[verIdxBase + 1].a = 0;
                }
            }

            var lineLength = curLine.length;
            float width;
            width = LINE_WIDTH;

            var uvValue = 0f;
            uvs[verIdxBase + 0] = new Vector2(0, 0);
            uvs[verIdxBase + 1] = new Vector2(0.5f, 0);
            uvs[verIdxBase + 2] = new Vector2(0.5f, 1);
            uvs[verIdxBase + 3] = new Vector2(0, 1);
            uvs[verIdxBase + 4] = new Vector2(0.5f, 0);
            uvs[verIdxBase + 5] = new Vector2(1, 0);
            uvs[verIdxBase + 6] = new Vector2(0.5f, 1);
            uvs[verIdxBase + 7] = new Vector2(1, 1);

            var triangleIdxBase = lineIdx * 12;
            triangles[triangleIdxBase + 0] = verIdxBase + 0;
            triangles[triangleIdxBase + 1] = verIdxBase + 1;
            triangles[triangleIdxBase + 2] = verIdxBase + 2;

            triangles[triangleIdxBase + 3] = verIdxBase + 0;
            triangles[triangleIdxBase + 4] = verIdxBase + 2;
            triangles[triangleIdxBase + 5] = verIdxBase + 3;

            triangles[triangleIdxBase + 6] = verIdxBase + 4;
            triangles[triangleIdxBase + 7] = verIdxBase + 7;
            triangles[triangleIdxBase + 8] = verIdxBase + 5;

            triangles[triangleIdxBase + 9] = verIdxBase + 4;
            triangles[triangleIdxBase + 10] = verIdxBase + 6;
            triangles[triangleIdxBase + 11] = verIdxBase + 7;
            lineIdx++;

            lineMat.SetFloat("_RtsLineTilling", curLine.length);

            RTSClassPoolManager.RecoverLineInfo(curLine);
        }
    }
        
    private void CalculateLineVertices(LineInfo line, out Vector2 p1, out Vector2 p2)
    {
        // 在这里根据具体的线段信息，计算得到线段的起始点p1和终点p2
        // 例如，假设线段的起点在 (0, 0)，方向向右，长度为 length
        // 终点位置为 (length, 0)
        float length = line.length;
        p1 = new Vector2(0, 0);
        p2 = new Vector2(length, 0);
    }

    private void CalculateArrowVertices(LineInfo line, out Vector2 p1, out Vector2 p2, out  Vector2 p3, out Vector2 p4, out Vector2 arrow5, out Vector2 arrow6, out Vector2 arrow7, out Vector2 arrow8)
    {
        float arrowSize = 0.1f; // 箭头的大小，根据实际需求调整

        Vector2 arrowDirection = (line.endPos - line.startPos).normalized;
        Vector2 arrowNormal = new Vector2(-arrowDirection.y, arrowDirection.x);
        Vector2 verticalOffset = arrowNormal.normalized * LINE_WIDTH * (this._height / this.minHeight) / 4f;
        Vector2 verticalOffset2 = arrowNormal.normalized * LINE_WIDTH * (this._height / this.minHeight)/2f;
        Vector2 horizontalOffset = -arrowDirection * (arrowSize / 2f + 0.05f);
        Vector2 horizontalOffset2 = -arrowDirection * (arrowSize * 2);
        p1 = line.startPos - verticalOffset;
        p2 = line.startPos + verticalOffset;

        p3 = line.endPos + verticalOffset + horizontalOffset;
        p4 = line.endPos - verticalOffset + horizontalOffset;

        arrow5 = line.endPos + verticalOffset2 + horizontalOffset2;
        arrow6 = line.endPos - verticalOffset2 + horizontalOffset2;
        arrow7 = line.endPos + verticalOffset2;
        arrow8 = line.endPos - verticalOffset2;
        //arrow8 = line.endPos + horizontalOffset2;
        //var temp = line.endPos + horizontalOffset;
        //arrow5 = temp + arrowNormal * LINE_WIDTH;
        //arrow7 = temp + -arrowNormal * LINE_WIDTH;
        //arrow6 = temp + arrowDirection * arrowSize;
    }

    private void ReBuildMesh()
    {
        meshIsDirty = false;
        arrowMesh.Clear();
        lineMesh.Clear();
        assembleMesh.Clear();

        arrowMat?.SetTextureScale("_MainTex", new Vector2(1, 1 / (_height / minHeight)));
        //会导致拉出来的渐变线条的方向箭头拉伸变形，所以注释掉了。
        //lineMat?.SetTextureScale("_MainTex", new Vector2(1, 1 / (_height / minHeight)));
        
        CalculateMesh(vertices, uvs, tangents, colors, triangles, arrows, LINE_MAX_COUNT);
        CalculateMeshSpecial(vertices2, uvs2, tangents2, colors2, triangles2, lines, Pre_LINE_MAX_COUNT);
        CalculateMesh(vertices3, uvs3, tangents3, colors3, triangles3, assemblelines, Pre_LINE_MAX_COUNT);
        CalculateMesh(vertices4, uvs4, tangents4, colors4, triangles4, warningLines, Pre_LINE_MAX_COUNT);
        arrowMesh.vertices = vertices;
        arrowMesh.uv = uvs;
        arrowMesh.colors = colors;
        arrowMesh.triangles = triangles;
        arrowMesh.tangents = tangents;

        arrowMesh.RecalculateNormals();
        arrowMesh.RecalculateBounds();

        lineMesh.vertices = vertices2;
        lineMesh.uv = uvs2;
        lineMesh.colors = colors2;
        lineMesh.triangles = triangles2;
        lineMesh.tangents = tangents2;

        lineMesh.RecalculateNormals();
        lineMesh.RecalculateBounds();
        
        assembleMesh.vertices = vertices3;
        assembleMesh.uv = uvs3;
        assembleMesh.colors = colors3;
        assembleMesh.triangles = triangles3;
        assembleMesh.tangents = tangents3;

        assembleMesh.RecalculateNormals();
        assembleMesh.RecalculateBounds();
        
        warningMesh.vertices = vertices4;
        warningMesh.uv = uvs4;
        warningMesh.colors = colors4;
        warningMesh.triangles = triangles4;
        warningMesh.tangents = tangents4;

        warningMesh.RecalculateNormals();
        warningMesh.RecalculateBounds();
    }


    public void SetFollowTarget(Transform target)
    {
        followTrans = target;
    }

    public void SetIsDirty()
    {
        meshIsDirty = true;
    }
    private List<int> changedColorList = new List<int>(128);
    private void ChangeLinesColor()
    {
        if (changedColorList!=null && changedColorList.Count>0)
        {
            changedColorList.Clear();
            SetIsDirty();
        }
    }

    public void ChangeLineColor(int lineId, int team)
    {
        var color = BattleUtils.GetColorByType(team);
        for (int i = 0; i < arrows.Count; i++)
        {
            var line = arrows[i];
            if (line.id == lineId)
            {
                line.color = color;
                changedColorList.Add(lineId);
                arrows[i] = line;
                break;
            }
        }
        RTSLuaCallCSharpManager.ChangeMarchPathPointColor(lineId, color);
    }
    public uint AddLine(LineInfo line)
    {
        line.id = lineID;

        if (line.isPart && line.length > LINE_SEGMENT_MAX)
        {
            var linePointOffset = (line.endPos - line.startPos).normalized * LINE_SEGMENT_MAX;
            var partLine = RTSClassPoolManager.GetLineInfo();
            partLine.Copy(line);
            line.isHeadPart = true;
            line.endPos = line.startPos + linePointOffset;
            partLine.isHeadPart = false;
            partLine.startPos = partLine.endPos - linePointOffset;

            if (line.lineType == LineType.line)
            {
                lines.Add(partLine);
            }
            else if (line.lineType == LineType.assembly)
            {
                assemblelines.Add(partLine);
            }
            else if (line.lineType == LineType.warning)
            {
                warningLines.Add(partLine);
            }
            else
            {
                arrows.Add(partLine);
            }
        }
        else if (line.isPart)
        {
            line.isPart = false;
        }

        if (line.lineType == LineType.line)
        {
            lines.Add(line);
        }
        else if (line.lineType == LineType.assembly)
        {
            assemblelines.Add(line);
        }
        else if (line.lineType == LineType.warning)
        {
            warningLines.Add(line);
        }
        else
        {
            arrows.Add(line);
        }
        meshIsDirty = true;

        return line.id;
    }

    public void DelLine(uint targetID)
    {
        for (int i = arrows.Count - 1; i >= 0; i--)
        {
            var curLine = arrows[i];
            if (curLine.id == targetID)
            {
                RTSClassPoolManager.RecoverLineInfo(arrows[i]);
                arrows.RemoveAt(i);
                if (curLine.isPart && i > 0 && arrows[i - 1].isPart)
                {
                    RTSClassPoolManager.RecoverLineInfo(arrows[i - 1]);
                    arrows.RemoveAt(i - 1);
                }
                break;
            }
        }
        for (int i = assemblelines.Count - 1; i >= 0; i--)
        {
            var curLine = assemblelines[i];
            if (curLine.id == targetID)
            {
                RTSClassPoolManager.RecoverLineInfo(assemblelines[i]);
                assemblelines.RemoveAt(i);
                if (curLine.isPart && i > 0 && assemblelines[i - 1].isPart)
                {
                    RTSClassPoolManager.RecoverLineInfo(assemblelines[i - 1]);
                    assemblelines.RemoveAt(i - 1);
                }
                break;
            }
        }
        for (int i = lines.Count - 1; i >= 0; i--)
        {
            var curLine = lines[i];
            if (curLine.id == targetID)
            {
                RTSClassPoolManager.RecoverLineInfo(lines[i]);
                lines.RemoveAt(i);
                if (curLine.isPart && i > 0 && lines[i - 1].isPart)
                {
                    RTSClassPoolManager.RecoverLineInfo(lines[i - 1]);
                    lines.RemoveAt(i - 1);
                }
                break;
            }
        }
        for (int i = warningLines.Count - 1; i >= 0; i--)
        {
            var curLine = warningLines[i];
            if (curLine.id == targetID)
            {
                RTSClassPoolManager.RecoverLineInfo(warningLines[i]);
                warningLines.RemoveAt(i);
                if (curLine.isPart && i > 0 && warningLines[i - 1].isPart)
                {
                    RTSClassPoolManager.RecoverLineInfo(warningLines[i - 1]);
                    warningLines.RemoveAt(i - 1);
                }
                break;
            }
        }
        meshIsDirty = true;
    }

    public static Vector3 V2ToV3(Vector2 v2)
    {
        return new Vector3(v2.x, 0, v2.y);
    }

    public static Vector2 V3ToV2(Vector3 v3)
    {
        return new Vector2(v3.x, v3.z);
    }

    private Dictionary<uint,List<uint>> multLines = new Dictionary<uint,List<uint>>(32);


    public void DelMultiLines(uint id,bool deleteInMap = false)
    {
        List<uint> multiLine = null;
        multLines.TryGetValue(id, out multiLine);
        if (multiLine != null)
        {
            for (int i = 0; i < multiLine.Count; i++)
            {
                DelLine(multiLine[i]);
            }
            RecoverLineId(multiLine);
            if (deleteInMap)
            {
                multLines.Remove(id);
            }
        }
    }

    public uint AddMultiLines(LineInfo originalLineInfo,Vector3[] pathList)
    {
        uint lineId = 0;
        List<uint> lines = GetLineIdFromPool();
        for (int i = 0; i < pathList.Length - 1; i++)
        {
            var info = RTSClassPoolManager.GetLineInfo();

            info.color = originalLineInfo.color;
            info.startPos = new Vector2(pathList[i].x, pathList[i].z);
            info.endPos = new Vector2(pathList[i + 1].x, pathList[i + 1].z);
            info.speed = originalLineInfo.speed;
            info.isPart = false;
            info.isHeadPart = false;
            info.team = originalLineInfo.team;
            info.lineType = originalLineInfo.lineType;
            lineId = AddLine(info);
            lines.Add(lineId);
        }

        if (!multLines.ContainsKey(lineId))
        {
            multLines.Add(lineId,lines);
        }

        return lineId;
    }
    
    public uint AddMultiLines(LineInfo originalLineInfo,int startIndex, List<Vector3> pathList)
    {
        uint lineId = 0;
        List<uint> lines = GetLineIdFromPool();
        for (int i = 0; i < pathList.Count - 1; i++)
        {
            var info = RTSClassPoolManager.GetLineInfo();

            info.color = originalLineInfo.color;
            info.startPos = new Vector2(pathList[i].x, pathList[i].z);
            info.endPos = new Vector2(pathList[i + 1].x, pathList[i + 1].z);
            info.speed = originalLineInfo.speed;
            info.isPart = false;
            info.isHeadPart = false;
            info.team = originalLineInfo.team;
            info.lineType = originalLineInfo.lineType;
            lineId = AddLine(info);
            lines.Add(lineId);
        }

        if (!multLines.ContainsKey(lineId))
        {
            multLines.Add(lineId,lines);
        }

        return lineId;
    }

    public uint AddMultiLines(LineInfo line,List<Vector2> pathList)
    {
        uint lineId = 0;
        List<uint> lines = GetLineIdFromPool();
        for (int i = 0; i < pathList.Count - 1; i++)
        {
            var info = RTSClassPoolManager.GetLineInfo();
            info.color = line.color;
            info.startPos = pathList[i];
            info.endPos = pathList[i + 1];
            info.speed = line.speed;
            info.isPart = false;
            info.isHeadPart = false;
            info.team = line.team;
            info.lineType = line.lineType;
            lineId = AddLine(info);
            lines.Add(lineId);
        }

        if (!multLines.ContainsKey(lineId))
        {
            multLines.Add(lineId,lines);
        }
        return lineId;
    }
    
    private List<uint> GetLineIdFromPool()
    {
        if (lineIdPool.Count == 0)
        {
            return new List<uint>(lineLength - 1);
        }
        else
        {
            var index = lineIdPool.Count - 1;
            var list = lineIdPool[index];
            lineIdPool.RemoveAt(index);
            list.Clear();
            return list;
        }
    }

    private void RecoverLineId(List<uint> lineId)
    {
        lineId.Clear();
        lineIdPool.Add(lineId);
    }

    public static float GetLineScaleByTeam(int team)
    {
        if (team == 0)
        {
            return GetInstance().selfScale;
        }
        return 1;
    }

    public static float GetLineScaleByMonsterType(RtsNpcType npcType)
    {
        if (npcType == RtsNpcType.NPC_MIRACLE_REINFORCE || npcType == RtsNpcType.NPC_MIRACLE_MOBILIZATION)
        {
            return GetInstance().selfScale;
        }
        return 1;
    }
}
